by Gene Olafsen
In This Chapter
This chapter describes the function and implementation of OLE containers. In previous chapters, you built various COM servers: active document, automation, and controls. With the exception of automation servers, there is still a need to explore client-side issues for active documents and ActiveX control containment.
An active document container is an application that supports the in-place activation of an active document server. The two most popular active document containers are the Microsoft Office Binder and Internet Explorer. Although the Office Binder application has been shipping for a number of years, unless your line of business calls for its use, you probably ignore this application when it is installed with Office. The purpose of the binder program is to organize documents of various types: Word, Excel, and PowerPoint, by project. Thus, when you want to work on the TideWater account, you simply open the binder project, and the associated files appear in a pane that anchors to the left of the application while Word, Excel, and so on, activate in the remaining client area.
Likewise, Internet Explorer is an active document container. You can demonstrate this for yourself by entering the path and name of a file in the Address field, and Explorer will activate the appropriate application in the space usually reserved for the HTML content. Notice as well that IEs help menu merges with Word, producing a composite menu of both applications. See Figure 15.1 for an illustration of this document containment and menu merging.
Figure 15.1 An active document container.
The active document container specification is a variation on the original OLE document container specification. The major difference is that active document server objects must populate the client area of the container application when they become in-place active. Thus, your container adopts the menus and toolbars of the document server and presents them as its own. The details of merging menus and toolbars are not a trivial operation. However, MFC provides a number of classes that make this behavior nearly painless.
Applications that claim active document containment must implement a number of interfaces. These interfaces represent the contract guaranteeing that the necessary functionality is available at such time as the document server requires it.
A container is responsible for providing a document server with a place, usually a file, to store its contents. In the world of COM, the concept of a container providing a server with a file into which it stores its contents indicates that the container provides an IStorage interface.
The IStorage interface is central to the concept of COMs structured storage. Structured storage manages data in a hierarchical format within a single physical file. The components of structured storage are storages and streams. Storages can be thought of as directories in a traditional file system. Storages can contain other storages and/or can contain streams. This is akin to a directory containing other directories and/or files. Thus, streams can be thought of as files within a traditional file system. Streams contain an objects data (see Figure 15.2).
Figure 15.2 Storage and stream relationship.
It should not surprise you that the IStorage interface provides the methods and properties for creating and modifying storage objects. See Table 15.1 for a list and description of the IStorage interfaces member functions.
| Method | Description |
|---|---|
| CreateStream | Creates and opens a stream object in this storage object |
| OpenStream | Opens an existing stream object within this storage object |
| CreateStorage | Creates and opens a new storage object within this storage object |
| OpenStorage | Opens an existing storage object |
| CopyTo | Copies the contents of an open storage object into another storage object |
| MoveElementTo | Copies or moves a storage or stream from this storage object to another storage object |
| Commit | Completes an operation on a transacted storage object |
| Revert | Discards an operation on a transacted storage object |
| EnumElements | Returns an enumerator object of storages and streams in this object |
| DestroyElement | Removes the specified storage or stream from this storage object |
| RenameElement | Renames the specified storage or stream in this storage object |
| SetElementTimes | Sets the various time properties of this storage object |
| SetClass | Allows you to assign a specific CLSID to this storage object |
| SetStateBits | Stores up to 32 bits of state information in this storage object |
| Stat | Retrieves STATSTG for this storage object |
You can glean a lot of understanding of this interface by reviewing the methods. There are methods to create, rename, enumerate, and delete objects. These operations correspond nicely to those operations you perform using either a command-line interface or graphical shell of a traditional file system.
The Stat method enables you to retrieve information that is similar to that which you retrieve using the _stat runtime function. The properties that _stat returns reside in the STATSTG structure, which is defined as follows:
typedef struct tagSTATSTG
{
LPWSTR pwcsName;
DWORD type;
ULARGE_INTEGER cbSize;
FILETIME mtime;
FILETIME ctime;
FILETIME atime;
DWORD grfMode;
DWORD grfLocksSupported;
CLSID clsid;
DWORD grfStateBits;
DWORD reserved;
} STATSTG;
Objects that implement the IStream interface support operations that are similar to those you perform on files. Such operations include reading and writing data, as well as the file pointer type operations you perform with seek. See Table 15.2 for a list and description of the IStream interfaces member functions.